package com.liming.aftersales.service.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.lang.Assert;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.liming.aftersales.mapper.CustomerReviewMapper;
import com.liming.aftersales.service.CustomerReviewService;
import com.liming.auth.client.UserAuthClient;
import com.liming.common.constant.SystemConstants;
import com.liming.common.enums.ReviewReplyEnum;
import com.liming.common.enums.ReviewTypeEnum;
import com.liming.common.exception.BusinessException;
import com.liming.common.pojo.dto.aftersales.CustomerReviewPageQuery;
import com.liming.common.pojo.dto.aftersales.ProductReviewPage;
import com.liming.common.pojo.dto.order.user.mini.MiniOrderEvaluateDTO;
import com.liming.common.pojo.dto.order.user.mini.MiniProductEvaluateDTO;
import com.liming.common.pojo.entity.BaseEntity;
import com.liming.common.pojo.entity.aftersales.CustomerReview;
import com.liming.common.pojo.vo.PageVO;
import com.liming.common.pojo.vo.aftersales.CustomerReviewVO;
import com.liming.common.pojo.vo.dashboard.CustomerReviewTopCardVO;
import com.liming.common.pojo.vo.review.MiniProductCommentVO;
import com.liming.common.pojo.vo.review.MiniProductReviewVO;
import com.liming.common.util.BeanUtils;
import com.liming.common.util.PageUtils;
import com.liming.common.util.ThreadLocalUtils;
import com.liming.common.util.mybatisplus.MPUtil;
import lombok.AllArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.concurrent.CompletableFuture;

/**
 * @author liming
 * @date 2025/3/13
 */
@Service
@AllArgsConstructor
public class CustomerReviewServiceImpl extends ServiceImpl<CustomerReviewMapper, CustomerReview>
        implements CustomerReviewService, MPUtil<CustomerReview> {

    private final UserAuthClient userAuthClient;

    @Override
    public PageVO<CustomerReviewVO> reviewPage(CustomerReviewPageQuery query) {
        IPage<CustomerReview> rawPage = lambdaQuery()
                .like(StrUtil.isNotBlank(query.getNickname()), CustomerReview::getUserNickname, query.getNickname())
                .like(StrUtil.isNotBlank(query.getProductName()), CustomerReview::getProductName, query.getProductName())
                .like(StrUtil.isNotBlank(query.getOrderNo()), CustomerReview::getOrderNo, query.getOrderNo())
                .eq(ObjectUtil.isNotNull(query.getType()), CustomerReview::getType, query.getType())
                .eq(ObjectUtil.isNotNull(query.getAnonymous()), CustomerReview::getAnonymous, query.getAnonymous())
                .eq(ObjectUtil.isNotNull(query.getReply()), CustomerReview::getReply, query.getReply())
                .between(ObjectUtil.isNotNull(query.getMinRating()), CustomerReview::getRating, query.getMinRating(), query.getMaxRating())
                .between(ObjectUtil.isNotNull(query.getStartTime()), CustomerReview::getCreateTime, query.getStartTime(), query.getEndTime())
                .orderByDesc(BaseEntity::getCreateTime)
                .page(setPage(query));

        // 获取用户IDS
        List<Long> userIds = rawPage.getRecords().stream().map(CustomerReview::getUserId).toList();
        if (CollUtil.isEmpty(userIds)) {
            return PageUtils.emptyPage();
        }
        // 获取用户ID - 头像 Map
        Map<Long, String> idAndAvatarMap = userAuthClient.idAndAvatarMap(userIds);
        return PageUtils.convert(rawPage, customerReview -> {
            CustomerReviewVO vo = BeanUtils.toBean(customerReview, CustomerReviewVO.class);
            Long userId = customerReview.getUserId();
            vo.setAvatar(idAndAvatarMap.getOrDefault(userId, ""));
            return vo;
        });
    }

    @Override
    public CustomerReviewTopCardVO topCard() {
        CustomerReviewTopCardVO vo = new CustomerReviewTopCardVO();
        vo.setTotal(lambdaQuery().count());
        vo.setUnReply(lambdaQuery().eq(CustomerReview::getReply, ReviewReplyEnum.NO_REPLY.getCode()).count());
        double totalRating = lambdaQuery().list().stream().mapToDouble(CustomerReview::getRating).average().orElse(0.0);
        vo.setRating(Float.parseFloat(String.valueOf(totalRating)));
        vo.setProductReview(lambdaQuery().eq(CustomerReview::getType, ReviewTypeEnum.PRODUCT_REVIEW.getCode()).count());
        double productRating = lambdaQuery().eq(CustomerReview::getType, ReviewTypeEnum.PRODUCT_REVIEW.getCode()).list().stream().mapToDouble(CustomerReview::getRating).average().orElse(0.0);
        vo.setProductRating(Float.parseFloat(String.valueOf(productRating)));
        vo.setOrderReview(lambdaQuery().eq(CustomerReview::getType, ReviewTypeEnum.ORDER_REVIEW.getCode()).count());
        double orderRating = lambdaQuery().eq(CustomerReview::getType, ReviewTypeEnum.ORDER_REVIEW.getCode()).list().stream().mapToDouble(CustomerReview::getRating).average().orElse(0.0);
        vo.setOrderRating(Float.parseFloat(String.valueOf(orderRating)));
        return vo;
    }

    @Override
    public Boolean merchantReview(Long id, String content) {
        CustomerReview dbReview = lambdaQuery().eq(CustomerReview::getId, id).one();
        Assert.notNull((dbReview), () -> new BusinessException("评论不存在"));
        Assert.equals(dbReview.getReply(), ReviewReplyEnum.NO_REPLY.getCode(), () -> new BusinessException("评论已回复"));
        return lambdaUpdate()
                .eq(CustomerReview::getId, id)
                .set(CustomerReview::getReply, ReviewReplyEnum.REPLY.getCode())
                .set(CustomerReview::getReplyText, content)
                .set(CustomerReview::getReplyTime, LocalDateTime.now())
                .update();
    }

    @Override
    public List<MiniProductCommentVO> miniProductReviews(Long id) {
        List<CustomerReview> productReviews = lambdaQuery().eq(CustomerReview::getProductId, id).list();
        if (CollUtil.isEmpty(productReviews)) {
            return Collections.emptyList();
        }
        Map<Long, String> idAndAvatarMap = userAuthClient.idAndAvatarMap(productReviews.stream().map(CustomerReview::getUserId).toList());
        List<MiniProductCommentVO> result = BeanUtils.toBean(productReviews, MiniProductCommentVO.class);
        for (MiniProductCommentVO miniProductCommentVO : result) {
            Long userId = miniProductCommentVO.getUserId();
            miniProductCommentVO.setAvatarUrl(idAndAvatarMap.getOrDefault(userId, ""));
        }
        return result;
    }

    @Override
    public MiniProductReviewVO miniPageProductReviews(ProductReviewPage page) {
        MiniProductReviewVO result = new MiniProductReviewVO();
        Long productId = page.getId();
        IPage<CustomerReview> rawPage = lambdaQuery().eq(CustomerReview::getProductId, productId).page(setPage(page));
        List<CustomerReview> productReviews = rawPage.getRecords();
        if (CollUtil.isEmpty(productReviews)) {
            result.setComments(PageUtils.emptyPage(page));
            return result;
        }
        Map<Long, String> idAndAvatarMap = userAuthClient.idAndAvatarMap(productReviews.stream().map(CustomerReview::getUserId).toList());
        PageVO<MiniProductCommentVO> comments = PageUtils.convert(rawPage, customerReview -> {
            MiniProductCommentVO vo = BeanUtils.toBean(customerReview, MiniProductCommentVO.class);
            Long userId = vo.getUserId();
            vo.setAvatarUrl(idAndAvatarMap.getOrDefault(userId, ""));
            return vo;
        });
        // 总平分
        List<MiniProductCommentVO> productComments = miniProductReviews(productId);
        result.setRating(productComments.stream().map(MiniProductCommentVO::getRating).reduce(0F, Float::sum) / productComments.size());
        result.setGoodRatingPercentage(productComments.stream().map(MiniProductCommentVO::getRating).filter(rating -> rating >= 3.0F).toList().size() * 100.0F / productComments.size());
        result.setComments(comments);
        return result;
    }

    @Override
    public Long userReviewOrderCount() {
        return lambdaQuery().eq(CustomerReview::getUserId, ThreadLocalUtils.get(SystemConstants.ID)).eq(CustomerReview::getType, ReviewTypeEnum.ORDER_REVIEW.getCode()).count();
    }

    @Override
    public Integer canComment(Long orderId) {
        Long count = lambdaQuery().eq(CustomerReview::getOrderId, orderId).eq(CustomerReview::getType, ReviewTypeEnum.ORDER_REVIEW.getCode()).count();
        // 系统目前一个订单只能存在一个订单评价
        Assert.isTrue(count <= 1, () -> new BusinessException("一个订单存在多个评价"));
        return count == 0 ? 1 : 0;
    }

    @Override
    @Transactional
    public Boolean evaluate(MiniOrderEvaluateDTO miniOrderEvaluateDTO) {
        long userId = Long.parseLong(ThreadLocalUtils.get(SystemConstants.ID));
        CompletableFuture<Map<Long, String>> userIdAndAvatarFuture = CompletableFuture.supplyAsync(() -> userAuthClient.idAndAvatarMap(List.of(userId)));
        CompletableFuture<Map<Long, String>> userIdAndNicknameFuture = CompletableFuture.supplyAsync(userAuthClient::userIdsAndNickname);
        CompletableFuture.allOf(userIdAndAvatarFuture, userIdAndNicknameFuture).join();
        Map<Long, String> userIdAndAvatarMap = userIdAndAvatarFuture.join();
        Map<Long, String> userIdAndNicknameMap = userIdAndNicknameFuture.join();
        // 插入订单
        CustomerReview orderSave = BeanUtils.toBean(miniOrderEvaluateDTO, CustomerReview.class);
        orderSave.setUserId(userId);
        orderSave.setUserNickname(userIdAndNicknameMap.getOrDefault(userId, ""));
        orderSave.setUserAvatar(userIdAndAvatarMap.getOrDefault(userId, ""));
        orderSave.setType(ReviewTypeEnum.ORDER_REVIEW.getCode());
        orderSave.setReply(ReviewReplyEnum.NO_REPLY.getCode());
        Assert.isTrue(save(orderSave), () -> new BusinessException("增加订单评价失败"));
        // 插入订单商品
        List<MiniProductEvaluateDTO> productEvaluateList = miniOrderEvaluateDTO.getProductEvaluateList();
        List<CustomerReview> productSaveList = BeanUtils.toBean(productEvaluateList, CustomerReview.class);
        for (CustomerReview productEvaluate : productSaveList) {
            productEvaluate.setUserId(userId);
            productEvaluate.setUserNickname(userIdAndNicknameMap.getOrDefault(userId, ""));
            productEvaluate.setUserAvatar(userIdAndAvatarMap.getOrDefault(userId, ""));
            productEvaluate.setType(ReviewTypeEnum.PRODUCT_REVIEW.getCode());
            productEvaluate.setReply(ReviewReplyEnum.NO_REPLY.getCode());
            productEvaluate.setAnonymous(miniOrderEvaluateDTO.getAnonymous());
            productEvaluate.setOrderId(miniOrderEvaluateDTO.getOrderId());
            productEvaluate.setOrderNo(miniOrderEvaluateDTO.getOrderNo());
        }
        Assert.isTrue(saveBatch(productSaveList), () -> new BusinessException("增加订单商品评价失败"));
        return true;
    }
}
